package com.hitqz.robot.biz.schedule;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.cache.Cache;
import com.hitqz.robot.api.business.dto.RobotClientSummaryDto;
import com.hitqz.robot.api.business.dto.RobotCustomInfoDto;
import com.hitqz.robot.api.business.entity.*;
import com.hitqz.robot.api.dispatch.protocol.dto.RobotWarningDto;
import com.hitqz.robot.biz.config.PatrolProperties;
import com.hitqz.robot.biz.service.*;
import com.hitqz.robot.common.file.core.FileProperties;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

@Component
@Slf4j
@RequiredArgsConstructor
public class ServerSchedule {

    private final CvdStoveService cvdStoveService;
    private final GasDetectService gasDetectService;
    private final CvdVoiceService cvdVoiceService;
    private final CvdQuestionAnswerService cvdQuestionAnswerService;
    private final FileProperties fileProperties;
    private final RestTemplate restTemplate;
    private final CvdStoveHistoryService cvdStoveHistoryService;

    @Value("${convert.text-to-voice}")
    private String textToVoiceUrl;

    @Value("${gas-threshold.c3h10si:100000}")
    private double c3h10siThreshold;
    @Value("${gas-threshold.h2:100000}")
    private double h2Threshold;
    @Value("${gas-threshold.c3h6:100000}")
    private double c3h6Threshold;

    /**
     * 自动关炉
     */
    @Scheduled(cron = "0/5 * * * * ?")
    private void closeCvdStove() {
        List<CvdStoveEntity> list = cvdStoveService.list(Wrappers.<CvdStoveEntity>lambdaQuery()
                .eq(CvdStoveEntity::getStatus, "1"));
        List<CvdStoveEntity> updateList = list.stream().filter(v -> {
            LocalDateTime endTime = v.getEndTime();
            if (endTime != null && endTime.isBefore(LocalDateTime.now())) {
                return true;
            }
            return false;
        }).toList();
        if (updateList.size() > 0) {
            updateList.forEach(v -> {
                v.setStatus("0");//关炉
                v.setLastRunningTime(v.getEndTime());//设置最后运行时间
            });
            cvdStoveService.updateBatchById(updateList);
            for (CvdStoveEntity entity : updateList) {
                //更新炉子实际关炉时间
                String execNo = entity.getExecNo();
                cvdStoveHistoryService.lambdaUpdate()
                        .eq(CvdStoveHistoryEntity::getExecNo, execNo)
                        .set(CvdStoveHistoryEntity::getStatus, entity.getStatus())
                        .set(CvdStoveHistoryEntity::getLastRunningTime, entity.getLastRunningTime())
                        .set(CvdStoveHistoryEntity::getActualEndTime, entity.getLastRunningTime())
                        .set(CvdStoveHistoryEntity::getUpdateTime, LocalDateTime.now())
                        .update();
            }
        }
    }


    /**
     * 气体检测
     */
    @Scheduled(cron = "0/15 * * * * ?")
    private void detectGas() {
        try {
            Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
            Iterable<String> cacheKeys = posInfoDtoCache.asMap().keySet();
            String firstKey = cacheKeys.iterator().hasNext() ? cacheKeys.iterator().next() : null;
            RobotClientSummaryDto robotClientSummaryDto = firstKey != null ? posInfoDtoCache.getIfPresent(firstKey) : null;
            if (robotClientSummaryDto != null && "在线".equals(robotClientSummaryDto.getStatus().getOnlineStatusStr())) {
                List<GasDetectEntity> saveList = new ArrayList<>();
                List<RobotWarningDto> warningList = new ArrayList<>();
                String posCode = robotClientSummaryDto.getPosition().getLaserPos().getNearPosCode();
                String robotSn = robotClientSummaryDto.getStatus().getSn();
                String robotName = robotClientSummaryDto.getStatus().getName();
                List<RobotCustomInfoDto> homeShowInfo = robotClientSummaryDto.getHomeShowInfo();
                if (homeShowInfo == null) return;
                Map<String, RobotCustomInfoDto> map = homeShowInfo.stream().collect(Collectors.toMap(RobotCustomInfoDto::getKey, v -> v));
                RobotCustomInfoDto repC3h10Si = map.get("repC3h10Si");
                if (repC3h10Si != null && StringUtils.hasText(repC3h10Si.getValue())) {
                    String c3h10si = map.get("repC3h10Si").getValue().replaceAll("ppm", "");
                    double c3h10siValue = StringUtils.hasText(c3h10si) ? Double.parseDouble(c3h10si) : 0;
                    if (c3h10siValue > c3h10siThreshold) {
                        String content = "在地图点位%s的三甲基硅烷浓度为%s,已超过阈值浓度%s";
                        content = content.formatted(posCode, (c3h10siValue + "ppm"), (c3h10siThreshold + "ppm"));

                        GasDetectEntity gasDetectEntity = new GasDetectEntity();
                        gasDetectEntity.setType(1);
                        gasDetectEntity.setValue(repC3h10Si.getValue());
                        gasDetectEntity.setPosCode(posCode);
                        gasDetectEntity.setContent(content);
                        saveList.add(gasDetectEntity);

                        RobotWarningDto warningDto = new RobotWarningDto();
                        warningDto.setContent(content);
                        warningDto.setRobotSn(robotSn);
                        warningDto.setWarningObj("定时检测:气体泄漏");
                        warningDto.setLevel(1);
                        warningList.add(warningDto);
                    }
                }

                RobotCustomInfoDto repH2 = map.get("repH2");
                if (repH2 != null && StringUtils.hasText(repH2.getValue())) {
                    String h2 = map.get("repH2").getValue().replaceAll("ppm", "");
                    double h2Value = StringUtils.hasText(h2) ? Double.parseDouble(h2) : 0;
                    if (h2Value > h2Threshold) {
                        String content = "在地图点位%s的氢气浓度为%s,已超过阈值浓度%s";
                        content = content.formatted(posCode, (h2Value + "ppm"), (h2Threshold + "ppm"));
                        GasDetectEntity gasDetectEntity = new GasDetectEntity();
                        gasDetectEntity.setType(2);
                        gasDetectEntity.setValue(repH2.getValue());
                        gasDetectEntity.setPosCode(posCode);
                        gasDetectEntity.setContent(content);
                        saveList.add(gasDetectEntity);

                        RobotWarningDto warningDto = new RobotWarningDto();
                        warningDto.setContent(content);
                        warningDto.setRobotSn(robotSn);
                        warningDto.setWarningObj("定时检测:气体泄漏");
                        warningDto.setLevel(1);
                        warningList.add(warningDto);
                    }
                }

                RobotCustomInfoDto repC3h6 = map.get("repC3h6");
                if (repC3h6 != null && StringUtils.hasText(repC3h6.getValue())) {
                    String c3h6 = map.get("repC3h6").getValue().replaceAll("ppm", "");
                    double c3h6Value = StringUtils.hasText(c3h6) ? Double.parseDouble(c3h6) : 0;
                    if (c3h6Value > c3h6Threshold) {
                        String content = "在地图点位%s的丙烯浓度为%s,已超过阈值浓度%s";
                        content = content.formatted(posCode, (c3h6Value + "ppm"), (c3h6Threshold + "ppm"));
                        GasDetectEntity gasDetectEntity = new GasDetectEntity();
                        gasDetectEntity.setType(3);
                        gasDetectEntity.setValue(repC3h6.getValue());
                        gasDetectEntity.setPosCode(posCode);
                        gasDetectEntity.setContent(content);
                        saveList.add(gasDetectEntity);

                        RobotWarningDto warningDto = new RobotWarningDto();
                        warningDto.setContent(content);
                        warningDto.setRobotSn(robotSn);
                        warningDto.setWarningObj("定时检测:气体泄漏");
                        warningDto.setLevel(1);
                        warningList.add(warningDto);
                    }
                }

                if (!saveList.isEmpty()) {
                    gasDetectService.saveBatch(saveList);
                }
                for (RobotWarningDto dto : warningList) {
                    SpringUtil.getApplicationContext().publishEvent(dto);
                }
            }
        } catch (Exception e) {
            log.error("气体检测失败:{}", e.getMessage(), e);
        }
    }

    /**
     * 文字转语音
     */
    @Scheduled(fixedDelay = 1000L)
    private void textToVoice() {
        try {
            //语音包
            List<CvdVoiceEntity> list1 = cvdVoiceService.list(Wrappers.<CvdVoiceEntity>lambdaQuery()
                    .eq(CvdVoiceEntity::getMediaStatus, "0"));
            for (CvdVoiceEntity entity : list1) {
                this.textToVoice1(entity);
            }

            //问答库
            List<CvdQuestionAnswerEntity> list2 = cvdQuestionAnswerService.list(Wrappers.<CvdQuestionAnswerEntity>lambdaQuery()
                    .eq(CvdQuestionAnswerEntity::getMediaStatus, "0"));
            for (CvdQuestionAnswerEntity entity : list2) {
                this.textToVoice2(entity);
            }
        } catch (Exception e) {
            log.error("文字转语音失败:{}", e.getMessage(), e);
        }

    }

    private boolean textToVoice1(CvdVoiceEntity updateEntity) {
        String content = updateEntity.getContent();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.valueOf("application/json;UTF-8"));
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("text", content);
        HttpEntity<String> strEntity = new HttpEntity<String>(jsonObject.toString(), headers);
        JSONObject result = restTemplate.postForObject(textToVoiceUrl, strEntity, JSONObject.class);
        String message = result.getString("message");
        if (!StringUtils.hasText(message)) {
            throw new RuntimeException("文字转语音失败!");
        }
        String originalPath = message;
        String dirPath = fileProperties.getLocal().getBasePath() + File.separator + "guide_voice" + File.separator;
        if (!FileUtil.exist(dirPath)) {
            FileUtil.mkdir(dirPath);
        }
        String filePath = dirPath + updateEntity.getId() + "_" + System.currentTimeMillis() + ".wav";
        String relativePath = normalizePath(filePath).replace(normalizePath(fileProperties.getLocal().getBasePath()), "/sys-file");
        URL url = URLUtil.url(originalPath);
        FileUtil.writeFromStream(URLUtil.getStream(url), filePath);
        //更新语音文件路径
        updateEntity.setMediaUrl(relativePath);
        updateEntity.setMediaStatus("1");
        return cvdVoiceService.updateById(updateEntity);
    }

    private boolean textToVoice2(CvdQuestionAnswerEntity updateEntity) {
        String content = updateEntity.getAnswerContent();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.valueOf("application/json;UTF-8"));
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("text", content);
        HttpEntity<String> strEntity = new HttpEntity<String>(jsonObject.toString(), headers);
        JSONObject result = restTemplate.postForObject(textToVoiceUrl, strEntity, JSONObject.class);
        String originalPath = result.getString("message");
        if (!StringUtils.hasText(originalPath)) {
            throw new RuntimeException("文字转语音失败!");
        }
        String dirPath = fileProperties.getLocal().getBasePath() + File.separator + "answer_voice" + File.separator;
        if (!FileUtil.exist(dirPath)) {
            FileUtil.mkdir(dirPath);
        }
        String filePath = dirPath + updateEntity.getId() + "_" + System.currentTimeMillis() + ".wav";
        String relativePath = normalizePath(filePath).replace(normalizePath(fileProperties.getLocal().getBasePath()), "/sys-file");
        URL url = URLUtil.url(originalPath);
        FileUtil.writeFromStream(URLUtil.getStream(url), filePath);
        //更新语音文件路径
        updateEntity.setMediaUrl(relativePath);
        updateEntity.setMediaStatus("1");
        return cvdQuestionAnswerService.updateById(updateEntity);
    }


    // 工具方法：将路径统一转为 "/" 分隔
    private String normalizePath(String path) {
        return path.replace("\\", "/");
    }


}
